﻿/* 
 * Copyright (c) 2010 Letwory Interactive
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -- Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * -- Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * Original contributor: Nathan Letwory
 */

using System;

namespace VerseSharp
{
    public delegate void ObjectAnimRunCallback(ObjectAnimRunCommand command);

    public class ObjectAnimRunCommand : IVerseCommand
    {
        public CommandID ID { get { return CommandID.ObjectAnimRun; } }
        public uint NodeID;
        public UInt16 LinkID;
        public uint TimeS;
        public uint TimeF;
        public byte Mask;
        public byte Dimensions;
        public double[] Pos = null;
        public double[] Speed = null;
        public double[] Accel = null;
        public double[] Scale = null;
        public double[] ScaleSpeed = null;

        public void Deserialize(byte[] source, ref int pos)
        {
            double[] temp;
            NodeID = Utils.GetUInt32(source, ref pos);
            LinkID = Utils.GetUInt16(source, ref pos);
            TimeS = Utils.GetUInt32(source, ref pos);
            TimeF = Utils.GetUInt32(source, ref pos);
            Dimensions = Utils.GetUInt8(source, ref pos);

            temp = new double[Dimensions];

            Mask = Utils.GetUInt8(source, ref pos);

            for (int i = 0; i < Dimensions; i++)
            {
                temp[i] = Utils.GetReal64(source, ref pos);
            }

            SetPos(temp);

            if ((Mask & 1) == 1)
            {
                for (int i = 0; i < Dimensions; i++)
                {
                    temp[i] = Utils.GetReal64(source, ref pos);
                }

                SetSpeed(temp);
            }
            if ((Mask & 2) == 2)
            {
                for (int i = 0; i < Dimensions; i++)
                {
                    temp[i] = Utils.GetReal64(source, ref pos);
                }
                SetAccel(temp);
            }
            if ((Mask & 4) == 4)
            {
                for (int i = 0; i < Dimensions; i++)
                {
                    temp[i] = Utils.GetReal64(source, ref pos);
                }
                SetScale(temp);
            }
            if ((Mask & 8) == 8)
            {
                for (int i = 0; i < Dimensions; i++)
                {
                    temp[i] = Utils.GetReal64(source, ref pos);
                }
                SetScaleSpeed(temp);
            }
        }

        public void SetPos(double[] input)
        {
            if (Pos == null)
            {
                Pos = new double[input.Length];
            }
            Buffer.BlockCopy(input, 0, Pos, 0, input.Length);
        }

        public void SetSpeed(double[] input)
        {
            if (Speed == null)
            {
                Speed = new double[input.Length];
            }
            Buffer.BlockCopy(input, 0, Speed, 0, input.Length);
        }

        public void SetAccel(double[] input)
        {
            if (Accel == null)
            {
                Accel = new double[input.Length];
            }
            Buffer.BlockCopy(input, 0, Accel, 0, input.Length);
        }

        public void SetScale(double[] input)
        {
            if (Scale == null)
            {
                Scale = new double[input.Length];
            }
            Buffer.BlockCopy(input, 0, Scale, 0, input.Length);
        }

        public void SetScaleSpeed(double[] input)
        {
            if (ScaleSpeed == null)
            {
                ScaleSpeed = new double[input.Length];
            }
            Buffer.BlockCopy(input, 0, ScaleSpeed, 0, input.Length);
        }

        public void Serialize(byte[] destination, ref int pos)
        {
            Utils.PutUInt32(destination, ref pos, NodeID);
            Utils.PutUInt16(destination, ref pos, LinkID);
            Utils.PutUInt32(destination, ref pos, TimeS);
            Utils.PutUInt32(destination, ref pos, TimeF);

            Utils.PutUInt8(destination, ref pos, Dimensions);
            int maskPos = pos;
            pos++;

            for (int i = 0; i < Dimensions; i++)
            {
                Utils.PutReal64(destination, ref pos, Pos[i]);
            }

            if (Speed != null)
            {
                destination[maskPos] |= 1;
                for (int i = 0; i < Dimensions; i++)
                {
                    Utils.PutReal64(destination, ref pos, Speed[i]);
                }
            }
            if (Accel != null)
            {
                destination[maskPos] |= 2;
                for (int i = 0; i < Dimensions; i++)
                {
                    Utils.PutReal64(destination, ref pos, Accel[i]);
                }
            }
            if (Scale != null)
            {
                destination[maskPos] |= 4;
                for (int i = 0; i < Dimensions; i++)
                {
                    Utils.PutReal64(destination, ref pos, Scale[i]);
                }
            }
            if (Scale != null)
            {
                destination[maskPos] |= 8;
                for (int i = 0; i < Dimensions; i++)
                {
                    Utils.PutReal64(destination, ref pos, ScaleSpeed[i]);
                }
            }
        }
    }
}
